package com.csw.android.androidtest.module.event;

import com.csw.android.androidtest.ui.LogViewFragment;
import com.csw.android.dev_utils.utils.RxBus;

import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;

/**
 * 基于Rxjava实现的事件订阅发送处理，轻量级，仅同个进程内使用
 * <p>
 * 事件总线使用广播机制太过繁琐，很多第三方也纷纷实现了用于全局通信、模块解耦的事件收发框架。
 * <p>
 * 目前用的比较多的是eventbus，通过反射的方式查看某个类是否含有eventbus注解的方法，解析参数判断该方法订阅了什么类型的参数事件
 * 可以通过eventbus的注解指定方法执行在什么线程，是一个很方便的框架，若方法需要更新界面，可以直接指定为主线程，这样不管发送方在什么线程
 * 都会切换到主线程。
 * <p>
 * 但我个人对rxjava比较钟爱，rxjava本身也是观察者模式，也提供了基于rxjava的订阅机制，可以方便的实现链式调用和
 * 线程切换，这里稍微封装了个RxBus的类，也算致敬eventBus，感谢为开源做贡献的程序员，代码敲起来更愉快了，多看
 * 这些框架的源码会受益匪浅。
 */
public class RxBusTest extends LogViewFragment {

    private Disposable disposable;

    @Override
    public void initListener() {
        super.initListener();
        //从RxBus注册某类型的可观察者对象，然后切换通知线程并订阅消息
        disposable = RxBus.Companion.getDefault().toObservable(RxBusOnTestData.class)
                .observeOn(AndroidSchedulers.mainThread())
                .doOnNext(new Consumer<RxBusOnTestData>() {
                    @Override
                    public void accept(RxBusOnTestData rxBusOnTestData) throws Exception {
                        logView.addLog(rxBusOnTestData.v1);
                        logView.addLog(rxBusOnTestData.v2);
                        logView.addLog(rxBusOnTestData.v3);
                    }
                })
                .subscribe();
    }

    @Override
    public void initData() {
        super.initData();
        //发送事件
        RxBus.Companion.getDefault().post(new RxBusOnTestData("stringValue", 2, 2.0));
    }

    @Override
    public void onDestroyView() {
        //取消订阅
        disposable.dispose();
        disposable = null;
        super.onDestroyView();
    }


    private static class RxBusOnTestData {
        private final String v1;
        private final int v2;
        private final double v3;

        public RxBusOnTestData(String v1, int v2, double v3) {
            this.v1 = v1;
            this.v2 = v2;
            this.v3 = v3;
        }

        public String getV1() {
            return v1;
        }

        public int getV2() {
            return v2;
        }

        public double getV3() {
            return v3;
        }
    }
}
